﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HerGoS.Interfaces
{
    public class MD5HashGenerator
    {
        public static String GenerateKey(Object sourceObject)
        {
            String hashString;

            if (sourceObject == null)
            {
                throw new ArgumentNullException("Null as parameter is not allowed");
            }
            else
            {
                //We determine if the passed object is really serializable.
                try
                {
                    hashString = ComputeHash(ObjectToByteArray(sourceObject));
                    return hashString;
                }
                catch (System.Reflection.AmbiguousMatchException ame)
                {
                    throw new ApplicationException("Could not definitely decide if object is serializable. Message:" + ame.Message);
                }
            }
        }

        private static string ComputeHash(byte[] objectAsBytes)
        {
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            try
            {
                byte[] result = md5.ComputeHash(objectAsBytes);

                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = 0; i < result.Length; i++)
                {
                    sb.Append(result[i].ToString("X2"));
                }

                // And return it
                return sb.ToString();
            }
            catch (ArgumentNullException ane)
            {
                return null;
            }
        }
        private static readonly Object locker = new Object();
        private static byte[] ObjectToByteArray(Object objectToSerialize)
        {
            System.IO.MemoryStream fs = new System.IO.MemoryStream();
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            try
            {
                lock (locker)
                {
                    formatter.Serialize(fs, objectToSerialize);
                }
                return fs.ToArray();
            }
            catch (System.Runtime.Serialization.SerializationException se)
            {
                return null;
            }
            finally
            {
                fs.Close();
            }
        }
    }
}
